--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_https_wss_side_sniffing.py
Displaying Raw • Download
tests/backend/test_https_wss_side_sniffing.py b1b9846ac58289ad2ac7f6564863fc97dd720128 (b1b9846a) Text, 5.21 KB
T8b949e"""HTTPS/WSS: local API traffic must be TLS-only (no plain HTTP on the same port)."""
Tff7b72import T7ee787os
Tff7b72import T7ee787socket
Tff7b72import T7ee787ssl
Tff7b72import T7ee787tempfile
Tff7b72from T7ee787datetime Tff7b72import Te6edf3UTCTb4b4b4, Te6edf3datetimeTb4b4b4, Te6edf3timedelta
Tff7b72import T7ee787aiohttp
Tff7b72import T7ee787pytest
Tff7b72from T7ee787aiohttp Tff7b72import Te6edf3web
Tff7b72from T7ee787cryptography Tff7b72import Te6edf3x509
Tff7b72from T7ee787cryptographyT7ee787.T7ee787hazmatT7ee787.T7ee787backends Tff7b72import Te6edf3default_backend
Tff7b72from T7ee787cryptographyT7ee787.T7ee787hazmatT7ee787.T7ee787primitives Tff7b72import Te6edf3hashesTb4b4b4, Te6edf3serialization
Tff7b72from T7ee787cryptographyT7ee787.T7ee787hazmatT7ee787.T7ee787primitivesT7ee787.T7ee787asymmetric Tff7b72import Te6edf3rsa
Tff7b72from T7ee787cryptographyT7ee787.T7ee787x509T7ee787.T7ee787oid Tff7b72import Te6edf3NameOID
Tff7b72def Td2a8ff_make_self_signed_cert_and_keyTb4b4b4(Te6edf3cert_pathTb4b4b4: Tffa657strTb4b4b4, Te6edf3key_pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3private_key Tff7b72= Te6edf3rsaTff7b72.Td2a8ffgenerate_private_keyTb4b4b4(
Te6edf3public_exponentTff7b72=T79c0ff65537Tb4b4b4,
Te6edf3key_sizeTff7b72=T79c0ff2048Tb4b4b4,
Te6edf3backendTff7b72=Te6edf3default_backendTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3subject Tff7b72= Te6edf3issuer Tff7b72= Te6edf3x509Tff7b72.Td2a8ffNameTb4b4b4(
Tb4b4b4[
Te6edf3x509Tff7b72.Td2a8ffNameAttributeTb4b4b4(Te6edf3NameOIDTff7b72.Td2a8ffCOUNTRY_NAMETb4b4b4, Ta5d6ff"Ta5d6ffUSTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3x509Tff7b72.Td2a8ffNameAttributeTb4b4b4(Te6edf3NameOIDTff7b72.Td2a8ffCOMMON_NAMETb4b4b4, Ta5d6ff"Ta5d6fflocalhostTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Te6edf3cert Tff7b72= Tb4b4b4(
Te6edf3x509Tff7b72.Td2a8ffCertificateBuilderTb4b4b4(Tb4b4b4)
Tff7b72.Td2a8ffsubject_nameTb4b4b4(Te6edf3subjectTb4b4b4)
Tff7b72.Td2a8ffissuer_nameTb4b4b4(Te6edf3issuerTb4b4b4)
Tff7b72.Td2a8ffpublic_keyTb4b4b4(Te6edf3private_keyTff7b72.Td2a8ffpublic_keyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72.Td2a8ffserial_numberTb4b4b4(Te6edf3x509Tff7b72.Td2a8ffrandom_serial_numberTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72.Td2a8ffnot_valid_beforeTb4b4b4(Te6edf3datetimeTff7b72.Td2a8ffnowTb4b4b4(Te6edf3UTCTb4b4b4)Tb4b4b4)
Tff7b72.Td2a8ffnot_valid_afterTb4b4b4(Te6edf3datetimeTff7b72.Td2a8ffnowTb4b4b4(Te6edf3UTCTb4b4b4) Tff7b72+ Te6edf3timedeltaTb4b4b4(Te6edf3daysTff7b72=T79c0ff365Tb4b4b4)Tb4b4b4)
Tff7b72.Td2a8ffsignTb4b4b4(Te6edf3private_keyTb4b4b4, Te6edf3hashesTff7b72.Td2a8ffSHA256Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3default_backendTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3cert_pathTb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3cert_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3certTff7b72.Td2a8ffpublic_bytesTb4b4b4(Te6edf3serializationTff7b72.Td2a8ffEncodingTff7b72.Td2a8ffPEMTb4b4b4)Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3key_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(
Te6edf3private_keyTff7b72.Td2a8ffprivate_bytesTb4b4b4(
Te6edf3encodingTff7b72=Te6edf3serializationTff7b72.Td2a8ffEncodingTff7b72.Td2a8ffPEMTb4b4b4,
Tffa657formatTff7b72=Te6edf3serializationTff7b72.Td2a8ffPrivateFormatTff7b72.Td2a8ffPKCS8Tb4b4b4,
Te6edf3encryption_algorithmTff7b72=Te6edf3serializationTff7b72.Td2a8ffNoEncryptionTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8fftemp_storageTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3tempfileTff7b72.Td2a8ffTemporaryDirectoryTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3dTb4b4b4:
Tff7b72yield Te6edf3d
Tf0883e@pytestTff7b72.Td2a8fffixture
Tff7b72def Td2a8ffssl_context_and_certTb4b4b4(Te6edf3temp_storageTb4b4b4)Tb4b4b4:
Te6edf3cert_dir Tff7b72= Te6edf3temp_storage
Te6edf3cert_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cert_dirTb4b4b4, Ta5d6ff"Ta5d6ffcert.pemTa5d6ff"Tb4b4b4)
Te6edf3key_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3cert_dirTb4b4b4, Ta5d6ff"Ta5d6ffkey.pemTa5d6ff"Tb4b4b4)
Te6edf3_make_self_signed_cert_and_keyTb4b4b4(Te6edf3cert_pathTb4b4b4, Te6edf3key_pathTb4b4b4)
Te6edf3ctx Tff7b72= Te6edf3sslTff7b72.Td2a8ffSSLContextTb4b4b4(Te6edf3sslTff7b72.Td2a8ffPROTOCOL_TLS_SERVERTb4b4b4)
Te6edf3ctxTff7b72.Td2a8ffload_cert_chainTb4b4b4(Te6edf3cert_pathTb4b4b4, Te6edf3key_pathTb4b4b4)
Tff7b72return Te6edf3ctxTb4b4b4, Te6edf3cert_pathTb4b4b4, Te6edf3key_path
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_https_serves_over_tls_only_plain_http_gets_no_http_responseTb4b4b4(
Te6edf3ssl_context_and_certTb4b4b4,
Tb4b4b4)Tb4b4b4:
T8b949e"""TLS-only server must not emit a plaintext HTTP response to raw HTTP bytes.
Raw TCP clients should see handshake noise or close, not ``HTTP/`` headers.
"""
Te6edf3ssl_contextTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72= Te6edf3ssl_context_and_cert
Te6edf3app Tff7b72= Te6edf3webTff7b72.Td2a8ffApplicationTb4b4b4(Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffroot_handlerTb4b4b4(Te6edf3_requestTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3webTff7b72.Td2a8ffResponseTb4b4b4(Te6edf3textTff7b72=Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4)
Te6edf3appTff7b72.Td2a8ffrouterTff7b72.Td2a8ffadd_getTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4, Te6edf3root_handlerTb4b4b4)
Te6edf3runner Tff7b72= Te6edf3webTff7b72.Td2a8ffAppRunnerTb4b4b4(Te6edf3appTb4b4b4, Te6edf3keepalive_timeoutTff7b72=T79c0ff0Tb4b4b4)
Tff7b72await Te6edf3runnerTff7b72.Td2a8ffsetupTb4b4b4(Tb4b4b4)
Te6edf3site Tff7b72= Te6edf3webTff7b72.Td2a8ffTCPSiteTb4b4b4(Te6edf3runnerTb4b4b4, Ta5d6ff"Ta5d6ff127.0.0.1Ta5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3ssl_contextTff7b72=Te6edf3ssl_contextTb4b4b4)
Tff7b72await Te6edf3siteTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3port Tff7b72= Te6edf3siteTff7b72.Td2a8ff_serverTff7b72.Td2a8ffsocketsTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffgetsocknameTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff1Tb4b4b4]
Te6edf3client_ctx Tff7b72= Te6edf3sslTff7b72.Td2a8ffSSLContextTb4b4b4(Te6edf3sslTff7b72.Td2a8ffPROTOCOL_TLS_CLIENTTb4b4b4)
Te6edf3client_ctxTff7b72.Td2a8ffcheck_hostname Tff7b72= Tff7b72False
Te6edf3client_ctxTff7b72.Td2a8ffverify_mode Tff7b72= Te6edf3sslTff7b72.Td2a8ffCERT_NONE
Tff7b72async Tff7b72with Te6edf3aiohttpTff7b72.Td2a8ffClientSessionTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3sessionTb4b4b4:
Te6edf3resp Tff7b72= Tff7b72await Te6edf3sessionTff7b72.Td2a8ffgetTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffhttps://127.0.0.1:Tffd700{Te6edf3portTffd700}Ta5d6ff/Ta5d6ff"Tb4b4b4,
Te6edf3sslTff7b72=Te6edf3client_ctxTb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3respTff7b72.Td2a8ffstatus Tff7b72== T79c0ff200
Tff7b72assert Tb4b4b4(Tff7b72await Te6edf3respTff7b72.Td2a8fftextTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffokTa5d6ff"
Te6edf3sock Tff7b72= Te6edf3socketTff7b72.Td2a8ffsocketTb4b4b4(Te6edf3socketTff7b72.Td2a8ffAF_INETTb4b4b4, Te6edf3socketTff7b72.Td2a8ffSOCK_STREAMTb4b4b4)
Te6edf3sockTff7b72.Td2a8ffsettimeoutTb4b4b4(T79c0ff1.0Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3sockTff7b72.Td2a8ffconnectTb4b4b4(Tb4b4b4(Ta5d6ff"Ta5d6ff127.0.0.1Ta5d6ff"Tb4b4b4, Te6edf3portTb4b4b4)Tb4b4b4)
Te6edf3sockTff7b72.Td2a8ffsendallTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffGET / HTTP/1.0Tffea00\rTffea00\nTffea00\rTffea00\nTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3raw Tff7b72= Te6edf3sockTff7b72.Td2a8ffrecvTb4b4b4(T79c0ff1024Tb4b4b4)
Tff7b72except Tf85149TimeoutErrorTb4b4b4:
Te6edf3raw Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ff"
Tff7b72finallyTb4b4b4:
Te6edf3sockTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72assert Tff7b72not Te6edf3rawTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffHTTP/Ta5d6ff"Tb4b4b4)Tb4b4b4, Tb4b4b4(
Ta5d6ff"Ta5d6ffServer must not respond with plain HTTP when TLS is enabled; Ta5d6ff"
Ta5d6ff"Ta5d6ffplaintext would allow local side-sniffingTa5d6ff"
Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72await Te6edf3runnerTff7b72.Td2a8ffcleanupTb4b4b4(Tb4b4b4)
Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_wss_over_same_tls_portTb4b4b4(Te6edf3ssl_context_and_certTb4b4b4)Tb4b4b4:
T8b949e"""WebSocket on the TLS port must use WSS (encrypted transport)."""
Te6edf3ssl_contextTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72= Te6edf3ssl_context_and_cert
Te6edf3app Tff7b72= Te6edf3webTff7b72.Td2a8ffApplicationTb4b4b4(Tb4b4b4)
Tff7b72async Tff7b72def Td2a8ffws_handlerTb4b4b4(Te6edf3requestTb4b4b4)Tb4b4b4:
Te6edf3ws Tff7b72= Te6edf3webTff7b72.Td2a8ffWebSocketResponseTb4b4b4(Tb4b4b4)
Tff7b72await Te6edf3wsTff7b72.Td2a8ffprepareTb4b4b4(Te6edf3requestTb4b4b4)
Tff7b72await Te6edf3wsTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3ws
Te6edf3appTff7b72.Td2a8ffrouterTff7b72.Td2a8ffadd_getTb4b4b4(Ta5d6ff"Ta5d6ff/wsTa5d6ff"Tb4b4b4, Te6edf3ws_handlerTb4b4b4)
Te6edf3runner Tff7b72= Te6edf3webTff7b72.Td2a8ffAppRunnerTb4b4b4(Te6edf3appTb4b4b4, Te6edf3keepalive_timeoutTff7b72=T79c0ff0Tb4b4b4)
Tff7b72await Te6edf3runnerTff7b72.Td2a8ffsetupTb4b4b4(Tb4b4b4)
Te6edf3site Tff7b72= Te6edf3webTff7b72.Td2a8ffTCPSiteTb4b4b4(Te6edf3runnerTb4b4b4, Ta5d6ff"Ta5d6ff127.0.0.1Ta5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4, Te6edf3ssl_contextTff7b72=Te6edf3ssl_contextTb4b4b4)
Tff7b72await Te6edf3siteTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3port Tff7b72= Te6edf3siteTff7b72.Td2a8ff_serverTff7b72.Td2a8ffsocketsTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffgetsocknameTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff1Tb4b4b4]
Te6edf3client_ctx Tff7b72= Te6edf3sslTff7b72.Td2a8ffSSLContextTb4b4b4(Te6edf3sslTff7b72.Td2a8ffPROTOCOL_TLS_CLIENTTb4b4b4)
Te6edf3client_ctxTff7b72.Td2a8ffcheck_hostname Tff7b72= Tff7b72False
Te6edf3client_ctxTff7b72.Td2a8ffverify_mode Tff7b72= Te6edf3sslTff7b72.Td2a8ffCERT_NONE
Tff7b72async Tff7b72with Tb4b4b4(
Te6edf3aiohttpTff7b72.Td2a8ffClientSessionTb4b4b4(Tb4b4b4) Tff7b72as Te6edf3sessionTb4b4b4,
Te6edf3sessionTff7b72.Td2a8ffws_connectTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffwss://127.0.0.1:Tffd700{Te6edf3portTffd700}Ta5d6ff/wsTa5d6ff"Tb4b4b4,
Te6edf3sslTff7b72=Te6edf3client_ctxTb4b4b4,
Tb4b4b4) Tff7b72as Te6edf3wsTb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Tff7b72await Te6edf3wsTff7b72.Td2a8ffreceiveTb4b4b4(Tb4b4b4)
Tff7b72assert Te6edf3msgTff7b72.Td2a8fftype Tff7b72in Tb4b4b4(
Te6edf3aiohttpTff7b72.Td2a8ffWSMsgTypeTff7b72.Td2a8ffCLOSETb4b4b4,
Te6edf3aiohttpTff7b72.Td2a8ffWSMsgTypeTff7b72.Td2a8ffCLOSINGTb4b4b4,
Te6edf3aiohttpTff7b72.Td2a8ffWSMsgTypeTff7b72.Td2a8ffCLOSEDTb4b4b4,
Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72await Te6edf3runnerTff7b72.Td2a8ffcleanupTb4b4b4(Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────